﻿local rL=rLua
if not rL then return end
if not IGAS then return end
rL.GUI=rL.GUI or {ServerCache={}}
local GUI=rL.GUI
do
	IGAS:NewAddon("Cube.Mdl_Cube_Main")
	GUI.CubeMain=Cube_Main
	GUI.code=code
end
if not GUI.CubeMain then rL.GUI=nil return end
do
	IGAS:NewAddon("Cube.Mdl_rLua")

	rLuaForm=Frame("Cube_Main_rLuaForm_Exp",GUI.CubeMain)
	rLuaForm:SetPoint("TOPLEFT", GUI.CubeMain, "BOTTOMLEFT")
	rLuaForm:SetPoint("TOPRIGHT", GUI.CubeMain, "BOTTOMRIGHT")
	rLuaForm:SetBackdrop{bgFile="Interface\\TutorialFrame\\TutorialFrameBackground",edgeFile="Interface\\Tooltips\\UI-Tooltip-Border",tile=false,tileSize=8,edgeSize=8,insets={left=2,right=3,top=2,bottom=3}}
	rLuaForm.Height=114
	rLuaForm.MouseEnabled=true
	GUI.form=rLuaForm

	targetName = NormalButton("TargetName", rLuaForm)
	targetName.Height = 24
	targetName.Width = 60
	targetName.Style = "CLASSIC"
	targetName.Text = "目标"
	targetName:SetPoint("TOPLEFT", rLuaForm, "TOPLEFT", 6, -6)
	GUI.targetName=targetName

	sendTarget = ComboBox("Target", rLuaForm)
	sendTarget.Editable = true
	sendTarget:SetPoint("LEFT", targetName, "RIGHT", 4, 0)
	GUI.sendTarget=sendTarget

	ver = NormalButton("Ver", rLuaForm)
	ver.Height = 24
	ver.Width = 60
	ver.Style = "CLASSIC"
    ver.Text = "版本"
    ver:SetPoint("LEFT", sendTarget, "RIGHT", 4, 0)
	GUI.ver=ver

	send = NormalButton("Send", rLuaForm)
	send.Height = 24
	send.Width = 60
	send.Style = "CLASSIC"
    send.Text = "发送"
    send:SetPoint("LEFT", ver, "RIGHT",4,0)
	GUI.send=send
	
	serverInfo=FontString("ServerInfo",rLuaForm)
	serverInfo.Height=14
	serverInfo:SetPoint("TOPLEFT", targetName, "BOTTOMLEFT", 0, -4)
	GUI.serverInfo=serverInfo
	
	cboFunc = ComboBox("FuncList", rLuaForm)
    cboFunc.Editable = true
    cboFunc:SetPoint("TOPLEFT", serverInfo, "BOTTOMLEFT", 0, -4)
	GUI.cboFunc=cboFunc
	
	chkAutorun=CheckBox("Autorun",rLuaForm)
	chkAutorun.Text="自动运行"
	chkAutorun:SetPoint("LEFT",cboFunc,"RIGHT",4,0)
	GUI.chkAutorun=chkAutorun
	
	funcInfo=FontString("FuncInfo",rLuaForm)
	funcInfo:SetPoint("LEFT",chkAutorun,"RIGHT",4,0)
	GUI.funcInfo=funcInfo
	
	inject = NormalButton("Inject", rLuaForm)
	inject.Height = 24
	inject.Width = 60
	inject.Style = "CLASSIC"
    inject.Text = "注入函数"
    local width = inject:GetTextWidth()
	if ( width > 50 ) then
		inject:SetWidth(width + 20)
	else
		inject:SetWidth(60)
	end
    inject:SetPoint("TOPLEFT", cboFunc, "BOTTOMLEFT",0,-4)
	GUI.inject=inject

	runFunc = NormalButton("RunFunc", rLuaForm)
	runFunc.Height = 24
	runFunc.Width = 60
	runFunc.Style = "CLASSIC"
    runFunc.Text = "执行"
    runFunc:SetPoint("LEFT", inject, "RIGHT",4,0)
	GUI.runFunc=runFunc
	
	pull = NormalButton("Pull", rLuaForm)
	pull.Height = 24
	pull.Width = 60
	pull.Style = "CLASSIC"
    pull.Text = "获取"
    pull:SetPoint("LEFT", runFunc, "RIGHT",4,0)
	GUI.pull=pull
	
	injectAll = NormalButton("InjectAll", rLuaForm)
	injectAll.Height = 24
	injectAll.Width = 60
	injectAll.Style = "CLASSIC"
    injectAll.Text = "全部注入"
    injectAll:SetPoint("LEFT", pull, "RIGHT",4,0)
	GUI.injectAll=injectAll

	runFuncAll = NormalButton("RunFuncAll", rLuaForm)
	runFuncAll.Height = 24
	runFuncAll.Width = 60
	runFuncAll.Style = "CLASSIC"
    runFuncAll.Text = "全部执行"
    runFuncAll:SetPoint("LEFT", injectAll, "RIGHT",4,0)
	GUI.runFuncAll=runFuncAll

	statusOut={}
	GUI.statusOut=statusOut
	statusInc={}
	GUI.statusInc=statusInc
	
	function StatusNewOut(SID)
		local index=#statusOut+1
		local bar=StatusBar("StatusOut"..index,rLuaForm)
		bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-TargetingFrame-BarFill")
		bar.Height=12
		bar.Width=rLuaForm.Width-12
		bar:SetPoint("TOPLEFT",statusOut[index-1] or inject,"BOTTOMLEFT",0,-4)
		bar.text=bar:CreateFontString(nil,"ARTWORK","GameFontHighlight")
		bar.text:SetPoint("CENTER",bar,"CENTER")
		bar.SID=SID
		tinsert(statusOut,bar)
		rLuaForm.Height=rLuaForm.Height+bar.Height+4
		if statusInc[1] then statusInc[1]:ClearAllPoints() statusInc[1]:SetPoint("TOPLEFT",bar,"BOTTOMLEFT",0,-4) end
	end
	
	function StatusNewInc(SID)
		local index=#statusInc+1
		local bar=StatusBar("StatusInc"..index,rLuaForm)
		bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-TargetingFrame-BarFill")
		bar.Height=12
		bar.Width=rLuaForm.Width-12
		bar:SetPoint("TOPLEFT",statusInc[index-1] or statusOut[#statusOut] or inject,"BOTTOMLEFT",0,-4)
		bar.text=bar:CreateFontString(nil,"ARTWORK","GameFontHighlight")
		bar.text:SetPoint("CENTER",bar,"CENTER")
		bar.SID=SID
		tinsert(statusInc,bar)
		rLuaForm.Height=rLuaForm.Height+bar.Height+4
	end
	
	function StatusRemoveOut(index)
		local bar=statusOut[index]
		if statusOut[index+1] then statusOut[index+1]:SetPoint(bar:GetPoint(1)) end
		if index==#statusOut and statusInc[1] then statusInc[1]:ClearAllPoints() statusInc[1]:SetPoint("TOPLEFT",statusOut[index-1] or inject,"BOTTOMLEFT",0,-4) end
		rLuaForm.Height=rLuaForm.Height-bar.Height-4
		bar:Dispose()
		tremove(statusOut,index)
	end
	
	function StatusRemoveInc(index)
		local bar=statusInc[index]
		if statusInc[index+1] then statusInc[index+1]:SetPoint(bar:GetPoint(1)) end
		rLuaForm.Height=rLuaForm.Height-bar.Height-4
		bar:Dispose()
		tremove(statusInc,index)
	end
	
	function send:OnClick()
		if sendTarget.Text and sendTarget.Text:len()>0 then
			rL.SendObject(sendTarget.Text,{Type="RunCode",Code=rL.SimpCode(GUI.code.Text)})
		end
	end

	function inject:OnClick()
		if sendTarget.Text and sendTarget.Text:len()>0 and cboFunc.Text and cboFunc.Text:len()>0 then
			rL.SendObject(sendTarget.Text,{Type="SetFunc",Name=cboFunc.Text,Code=rL.SimpCode(GUI.code.Text),Autorun=chkAutorun.Checked})
		end
	end

	function runFunc:OnClick()
		if sendTarget.Text and sendTarget.Text:len()>0 and cboFunc.Text and cboFunc.Text:len()>0 then
			rL.SendObject(sendTarget.Text,{Type="RunFunc",Name=cboFunc.Text})
		end
	end

	function pull:OnClick()
		if sendTarget.Text and sendTarget.Text:len()>0 and cboFunc.Text and cboFunc.Text:len()>0 then
			rL.SendObject(sendTarget.Text,{Type="GetFunc",Name=cboFunc.Text})
		end
	end
	
	function injectAll:OnClick()
		if sendTarget.ItemCount>0 and cboFunc.Text and cboFunc.Text:len()>0 then
			rL.log(("Injecting function %s to %d clients."):format(cboFunc.Text, sendTarget.ItemCount))
			if IsShiftKeyDown() and IsControlKeyDown() and IsAltKeyDown() then
				for index, value in ipairs( sendTarget.Items ) do
					rL.SendObject(value,{Type="SetFunc",Name=cboFunc.Text,Code=rL.SimpCode(GUI.code.Text),Autorun=chkAutorun.Checked})
				end
			else
				rL.log("Ctrl-Alt-Shift must be pressed as a confirmation")
			end
		end
	end

	function runFuncAll:OnClick()
		if IsShiftKeyDown() and IsControlKeyDown() and IsAltKeyDown() then
			for index, value in ipairs( sendTarget.Items ) do
				rL.SendObject(value,{Type="RunFunc",Name=cboFunc.Text})
			end
		else
			rL.log("Ctrl-Alt-Shift must be pressed as a confirmation")
		end
	end

	function targetName:OnClick()
		if UnitName("target") then
			sendTarget.Text=UnitName("target")
			ver:Click()
		end
	end
	
	function Update()
		local reverseLookup={}
		for key,value in pairs(GUI.ServerCache) do tinsert(reverseLookup,key) end
		sendTarget:SetList(reverseLookup)
		
		local cache=GUI.ServerCache[sendTarget.Text]
		if cache then
			serverInfo.Text=("版本%s - %d个函数共%d字节"):format(cache.Ver,#cache.funcList,cache.Bytes)
			if cache.Latency then serverInfo.Text=serverInfo.Text..(" - %d ms"):format(cache.Latency*1000) end
			funcInfo.Text="未知函数"
			chkAutorun.Checked=false
			for index,info in ipairs(cache.FuncList) do
				if info.n==cboFunc.Text then
					funcInfo.Text=info.l.."字节"
					chkAutorun.Checked=info.a
				end
			end
			cboFunc:SetList(cache.funcList)
		else
			serverInfo.Text=""
		end
	end
	cboFunc.OnTextChanged=Update
	sendTarget.OnTextChanged=cboFunc.OnTextChanged
	GUI.Update=Update

	function ver:OnClick()
		rL.SendObject(sendTarget.Text,{Type="Ver",timeStamp=GetTime()})
	end
	
	function rL.SESSION_INC_ERROR(sender,ID,text,...)
		rL.log(("Inc %s-ID%d: "):format(sender,ID)..(text or ""):format(...))
	end
	
	function rL.SESSION_OUT_ERROR(sender,ID,text,...)
		rL.log(("Out %s-ID%d: "):format(sender,ID)..(text or ""):format(...))
	end
	
	StatusColor={["REQUEST"]={1.0,0.0,0.0},["SENDING"]={0.10,1.0,0.10},["LISTENING"]={0.8,0.8,0.0},}
	
	function rL.SESSION_INC_UPDATE(sender,SessionID)
		local Session=rL.Sessions_Inc[SessionID]
		if not Session then end
		for index,bar in pairs(statusInc) do
			if bar.SID==SessionID then
				bar:SetMinMaxValues(0,Session.Total)
				bar:SetValue(Session.Received)
				bar:SetStatusBarColor(unpack(StatusColor[Session.Status]))
				bar.text:SetText(("%s - %d: (%d / %d)"):format(Session.Target,SessionID,Session.Received,Session.Total))
				return
			end
		end
		StatusNewInc(SessionID)
		return rL.SESSION_INC_UPDATE(sender,SessionID)
	end
	
	function rL.SESSION_OUT_UPDATE(sender,SessionID)
		local Session=rL.Sessions_Out[SessionID]
		if not Session then end
		for index,bar in pairs(statusOut) do
			if bar.SID==SessionID then
				if Session.Status=="REQUEST" then
					bar:SetMinMaxValues(0,1)
					bar:SetValue(1)
					bar.text:SetText("正在建立连接...")
				else
					bar:SetMinMaxValues(0,Session.Total)
					bar:SetValue(Session.Sent)
					bar.text:SetText(("%s - %d: (%d / %d)"):format(Session.Target,SessionID,Session.Sent,Session.Total))
				end
				bar:SetStatusBarColor(unpack(StatusColor[Session.Status]))
				return
			end
		end
		StatusNewOut(SessionID)
		return rL.SESSION_OUT_UPDATE(sender,SessionID)
	end
	
	function rL.SESSION_INC_CLOSED(sender,SessionID,Reason)
		local Session=rL.Sessions_Inc[SessionID]
		if not Session then end
		for index,bar in pairs(statusInc) do
			if bar.SID==SessionID then
				StatusRemoveInc(index)
			end
		end
	end
	
	function rL.SESSION_OUT_CLOSED(sender,SessionID,Reason)
		local Session=rL.Sessions_Out[SessionID]
		if not Session then end
		for index,bar in pairs(statusOut) do
			if bar.SID==SessionID then
				StatusRemoveOut(index)
			end
		end
	end
	
end
